import { Component, OnInit } from '@angular/core'
import { FormBuilder, Validators, FormControl } from '@angular/forms'
import { BehaviorSubject, Observable } from 'rxjs'
import { debounceTime, switchMap, map } from 'rxjs/operators'
import { NzMessageService } from 'ng-zorro-antd'

import { CountryService } from '@shared/services/country.service'
import { ICountryQueryParams, BizAreaOptions } from '@shared/interfaces/common'
import { transCountriesToOptions, makeAllControlDirty, compareTwoCurrencies } from 'app/utils/helpers'
import { AcquirerStoreService } from '../acquirer-store.service'
import { AcquirerNewBaseClass } from '../baseClass'
import {
  emailReg,
  insNameENReg,
  insCodeReg,
  insNameMaxLength,
  insNameENMaxLength,
  insCodeLength,
  contactNameMaxLength,
  emailMaxLength,
} from 'app/utils/contraints'
import { NumConflictAsyncValidator } from 'app/utils/form-control.validator'
import { BusinessService } from '@shared/services/business.service'
import { EBizLevel } from '@shared/enums'
import { I18NService } from '@core'

@Component({
  selector: 'app-acquirer-new-base',
  templateUrl: './base.component.html',
  styleUrls: ['../../../../shared/styles/new-page-form.less'],
})
export class AcquirerNewBaseComponent extends AcquirerNewBaseClass implements OnInit {
  nationOptions$: Observable<{ label: string; value: string }[]> // 国家地区选项
  params: ICountryQueryParams
  searchChange$ = new BehaviorSubject({})

  compareCurrencyFn = compareTwoCurrencies

  errorTips = {}

  bizAreaOptions = BizAreaOptions

  constructor(
    public acquirerStore: AcquirerStoreService,
    public fb: FormBuilder,
    private msg: NzMessageService,
    private countryService: CountryService,
    private bizService: BusinessService,
    private i18n: I18NService,
  ) {
    super(fb, acquirerStore)
  }

  ngOnInit(): void {
    this.requestAll()
    this.initValidateForm()
  }

  requestAll(): void {
    this.renderCountries()
  }

  initValidateForm(): void {
    const { common } = this.acquirer.institution
    this.validateForm = this.fb.group({
      insName: [common.insName, [Validators.required, Validators.maxLength(insNameMaxLength)]],
      insNameEN: [
        common.insNameEN,
        [Validators.required, Validators.maxLength(insNameENMaxLength), Validators.pattern(insNameENReg)],
      ],
      insCode: new FormControl(common.insCode, {
        validators: [
          Validators.required,
          Validators.minLength(insCodeLength),
          Validators.maxLength(insCodeLength),
          Validators.pattern(insCodeReg),
        ],
        asyncValidators: [NumConflictAsyncValidator(this.bizService, '', EBizLevel.Institution)],
      }),
      nation: [common.address.nation, [Validators.required]],
      businessArea: [common.businessArea, [Validators.required]],
      currencies: [common.currencies, [Validators.required]],
      address: [common.address.address, [Validators.required]],
      contactName: [common.contact.name, [Validators.required, Validators.maxLength(contactNameMaxLength)]],
      contactEmail: [
        common.contact.email,
        [Validators.required, Validators.maxLength(emailMaxLength), Validators.pattern(emailReg)],
      ],
    })
    this.initErrorTips()
  }

  initErrorTips() {
    this.errorTips = {
      insName: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INSTITUTION.NAME') }),
        maxlength: this.trans('VALIDATION.MAX_LENGTH', { length: insNameMaxLength }),
      },
      insNameEN: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INSTITUTION.NAME_EN') }),
        maxlength: this.trans('VALIDATION.MAX_LENGTH', { length: insNameENMaxLength }),
        pattern: this.trans('VALIDATION.PATTERN.ALPHANUMERIC_SYMBOLS_ONLY'),
      },
      insCode: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INSTITUTION.CODE') }),
        maxlength: this.trans('VALIDATION.FIXED_LENGTH', { length: insCodeLength }),
        minlength: this.trans('VALIDATION.FIXED_LENGTH', { length: insCodeLength }),
        pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
        isNumTaken: this.trans('VALIDATION.CODE_EXISTS', { name: this.trans('GENERAL.INSTITUTION.CODE') }),
      },
      nation: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.COUNTRY_REGION') }),
      },
      businessArea: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('BIZ.ACQUIRER.BIZ_AREA') }),
      },
      currencies: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.TRANSACTION_CURRENCY') }),
      },
      address: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.ADDRESS') }),
      },
      contactName: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.CONTACT_NAME') }),
        maxlength: this.trans('VALIDATION.MAX_LENGTH', { length: contactNameMaxLength }),
      },
      contactEmail: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.EMAIL') }),
        maxlength: this.trans('VALIDATION.MAX_LENGTH', { length: emailMaxLength }),
        pattern: this.trans('VALIDATION.PATTERN.EMAIL'),
      },
    }
  }

  pushDataToStore(): void {
    const { common } = this.acquirer.institution
    const {
      insName,
      insNameEN,
      insCode,
      nation,
      businessArea,
      currencies,
      address,
      contactName,
      contactEmail,
    } = this.validateForm.value
    common.insName = insName
    common.insNameEN = insNameEN
    common.insCode = insCode
    common.businessArea = businessArea
    common.currencies = currencies
    common.contact.name = contactName
    common.contact.email = contactEmail
    common.address.nation = nation.codeAlpha3 || nation
    common.address.address = address
    this.acquirerStore.updateValue(this.acquirer)
  }

  public checkValid(): boolean {
    if (this.validateForm.valid) {
      this.pushDataToStore()
      this.msg.success(this.trans('GENERAL.NOTIFICATION.VALIDATION_SUCCESS'))
      return true
    } else {
      makeAllControlDirty(this.validateForm)
      this.msg.error(this.trans('GENERAL.NOTIFICATION.VALIDATION_FAIL'))
      return false
    }
  }

  trans(key: string, params?: Object): string {
    return this.i18n.fanyi(key, params)
  }

  private renderCountries(): void {
    this.nationOptions$ = this.searchChange$.asObservable().pipe(
      debounceTime(500),
      switchMap(_ => this.countryService.getCounties(this.params)),
      map(countries => transCountriesToOptions(countries)),
    )
  }
}
